﻿import store from '../store'
import Vue from 'vue'

function toBlob (base64str, filetype) {
  let bytes = window.atob(base64str)
  let n = bytes.length
  let u8arr = new Uint8Array(n)
  while (n--) {
    u8arr[n] = bytes.charCodeAt(n)
  }
  return new Blob([u8arr], {type: filetype})
}
// 一、根据字段名/常量等获取相应的值
const commonUse_defaultMethod = function (keyName, dataObject, fixedValue, rowObj, pPageObj) {
  // 键名: keyName; 值的集合: dataObject; 键值:keyValue, fixedValue: 常用的固定值的集合
  let keyValue = null
  if (typeof keyName !== 'string') {
    return keyName
  }
  if (keyName.indexOf('@') === 0 && keyName.substring(keyName.length - 1) !== '@') {
    keyValue = keyName.slice(1)
  } else if (keyName.indexOf('R.') === 0) {
    if (rowObj) {
      let inRowKey = keyName.split('.')
      keyValue = rowObj
      for (let i = 1; i < inRowKey.length; i++) {
        let k = inRowKey[i]
        for (let sKey in keyValue) {
          if (k === sKey) {
            keyValue = keyValue[sKey]
            if (!keyValue) {
              throw new Error(keyName + '表达式错误，在行数据中未找到' + sKey + '属性')
            }
            break
          }
        }
      }
    }
  } else if (keyName.indexOf('P.') === 0) {
    if (pPageObj) {
      let inRowKey = keyName.split('.')
      keyValue = pPageObj
      for (let i = 1; i < inRowKey.length; i++) {
        let k = inRowKey[i]
        for (let sKey in keyValue) {
          if (k === sKey) {
            keyValue = keyValue[sKey]
            if (!keyValue) {
              throw new Error(keyName + '表达式错误，在父页面数据中未找到' + sKey + '属性')
            }
            break
          }
        }
      }
    }
  } else if (keyName === '$_login_id' || keyName === '@__login_id@' || keyName === '__login_id') {
    keyValue = store.state.nameId
  } else if (keyName === '$_login_name' ||
            keyName === '$_user_name' ||
            keyName === '@__user_name@' ||
            keyName === '__user_name' ||
            keyName === '@__login_name@' ||
            keyName === '__login_name') {
    keyValue = store.state.userName
  } else if (keyName === '$_now' || keyName === '@__now@' || keyName === '__now') {
    keyValue = Vue.prototype.$getCurrentDate()
  } else if (keyName === '$_FormKey' && fixedValue) { // 页面的uid
    keyValue = fixedValue.formKey
  } else if (keyName === '$_PrimaryKey' && fixedValue) { // 流程相关的
    keyValue = fixedValue.primaryKey
  } else if (keyName === '$_Status' && fixedValue) { // 流程相关的
    keyValue = fixedValue.status
  } else if (keyName === '$_limit' && fixedValue) { // 页码相关的
    keyValue = fixedValue.limit
  } else if (keyName === '$_page' && fixedValue) { // 页码相关的
    keyValue = fixedValue.page
  } else if (keyName === '$_user_no' || keyName === '@__user_no@' || keyName === '__user_no') {
    keyValue = store.state.userNo
  } else if (keyName === '@__user_type@' || keyName === '__user_type') {
    keyValue = store.state.userType
  } else if (keyName === '@__role_no@' || keyName === '__role_no') {
    keyValue = store.state.roleNo
  } else if (keyName === '$_token') {
    keyValue = sessionStorage.getItem('token')
  } else {
    if (dataObject) {
      let hadTheKey = false
      let keyArr = keyName.split('.')
      keyValue = dataObject
      for (let i = 0; i < keyArr.length; i++) {
        let k = keyArr[i]
        for (let sKey in keyValue) {
          if (k === sKey) {
            hadTheKey = true
            keyValue = keyValue[sKey]
            break
          }
        }
      }
      // 如果在dataObject中没有对应的可以时,就等于该键值
      if (!hadTheKey) {
        keyValue = keyName
      }
    } else {
      keyValue = keyName
    }
  }
  return keyValue
}

// 二、设置控件/表格行事件的只读或隐藏的状态---------------开始
export function commonUse_setWidgetStatus (expressObj, dataObject, fixedValue, rowData, pPageObj) {
  // expressObj: 表达式的对象合集, dataObject: 数据值的集合, fixedValue: 常用的固定值的集合
  // 注：是隐藏、只读表达式，默认显示、可读，则返回 false
  let expressResult = false
  // 表达式对象的 key  的集合
  let expressObjKeysArray = Object.keys(expressObj)
  if (expressObjKeysArray.length) {
    let express = ''
    expressObjKeysArray.forEach((keyItem, keyItemIndex) => {
      // 数据中的keyItem(在没有$or_开头时，默认和表达式中的相同)
      let dataKeyItem = keyItem
      if (keyItemIndex) {
        // 判断是不是 || 计算形式
        // 默认情况下从第二个字段开始判断
        if (keyItem.indexOf('$or_') !== -1) {
          dataKeyItem = keyItem.slice(4)
          express += '||('
        } else {
          express += '&&('
        }
      } else {
        express = '('
      }
      // 需要判断 dataKeyItem 是全局的变量($G_)还是 当前行的变量
      let scopedRowData = null
      if (dataKeyItem.indexOf('$G_') !== -1) {
        // 总经理
        if (dataKeyItem === '$G_is_gm') {
          scopedRowData = store.state.roleNo && store.state.roleNo.indexOf('GM') !== -1
        } else if (dataKeyItem === '$G_is_cm') {
          // 客户经理
          scopedRowData = store.state.roleNo && store.state.roleNo.indexOf('CM') !== -1
        } else if (dataKeyItem === '$G_is_cashier') {
          // 出纳
          scopedRowData = store.state.roleNo && store.state.roleNo.indexOf('Cashier') !== -1
        }
      } else {
        // 该key对应在本行的数据值--用到的是dataKeyItem
        scopedRowData = dataObject[dataKeyItem]
        if (!dataObject[dataKeyItem] && dataObject[dataKeyItem] !== 0) {
          scopedRowData = null
        }
      }
      // 判断该值是数组还是对象
      if (Vue.prototype.$isArray(expressObj[keyItem])) {
        // 如果是数组，表示的多个值 || 运算
        for (let resultIndex = 0; resultIndex < expressObj[keyItem].length; resultIndex++) {
          for (let resultIndexKey in expressObj[keyItem][resultIndex]) {
            express = commonUse_setWidgetStatus_getValue(scopedRowData, resultIndexKey, expressObj[keyItem][resultIndex][resultIndexKey], express, dataObject, fixedValue, rowData, pPageObj)
            // 当表示式不是最后一个时
            if (Object.keys(expressObj[keyItem][resultIndex]).indexOf(resultIndexKey) !== Object.keys(expressObj[keyItem][resultIndex]).length - 1) {
              express += '&&'
            }
          }
          if (resultIndex !== expressObj[keyItem].length - 1) {
            express += '||'
          }
        }
      } else {
        // 如果是对象，表示的多个值 && 运算
        for (let key in expressObj[keyItem]) {
          express = commonUse_setWidgetStatus_getValue(scopedRowData, key, expressObj[keyItem][key], express, dataObject, fixedValue, rowData, pPageObj)
          // 当表示式不是最后一个时
          if (Object.keys(expressObj[keyItem]).indexOf(key) !== Object.keys(expressObj[keyItem]).length - 1) {
            express += '&&'
          }
        }
      }
      // 一个表达式计算完成，需要添加括号
      express += ')'
    })
    if (express) {
      expressResult = Vue.prototype.$selfdefineEval(express)
    }
  }
  return expressResult
}
// 获取值的方法
const commonUse_setWidgetStatus_getValue = function (scopedRowData, expressKey, expressRightValue, express, dataObject, fixedValue, rowData, pPageObj) {
  // 数组类型表示多个值 || 运算
  if (Vue.prototype.$isArray(expressRightValue)) {
    for (let keyIndex = 0; keyIndex < expressRightValue.length; keyIndex++) {
      // 判断expressRightValue对应的是值，还是变量
      let expressValue = commonUse_setWidgetStatus_getRightExpressValue(expressRightValue[keyIndex], dataObject, fixedValue, rowData, pPageObj)
      let leftKey = '"' + scopedRowData + '"'
      let rightKey = '"' + expressValue + '"'
      if (expressKey === '$eq') {
        express += leftKey + '==' + rightKey
      } else if (expressKey === '$neq') {
        express += leftKey + '!=' + rightKey
      }
      // 当后面还有数据时
      if (keyIndex !== expressRightValue.length - 1) {
        express += '||'
      }
    }
  } else {
    // 判断expressRightValue对应的是值，还是变量
    let expressValue = commonUse_setWidgetStatus_getRightExpressValue(expressRightValue, dataObject, fixedValue, rowData, pPageObj)
    let leftKey = '"' + scopedRowData + '"'
    let rightKey = '"' + expressValue + '"'
    if (expressKey.indexOf('$_') !== -1) {
      expressKey = expressKey.slice(2)
    }
    if (expressKey === '$eq') {
      express += leftKey + '==' + rightKey
    } else if (expressKey === '$neq') {
      express += leftKey + '!=' + rightKey
    } else if (expressKey === '$lt') {
      express += leftKey + '<' + rightKey
    } else if (expressKey === '$lte') {
      express += leftKey + '<=' + rightKey
    } else if (expressKey === '$gt') {
      express += leftKey + '>' + rightKey
    } else if (expressKey === '$gte') {
      express += leftKey + '>=' + rightKey
    }
  }
  return express
}
// 获取表达式右侧的值
const commonUse_setWidgetStatus_getRightExpressValue = function (expressRightKey, dataObject, fixedValue, rowData, pPageObj) {
  let inputKeyValue = ''
  let pageKey = expressRightKey.toString()
  inputKeyValue = commonUse_defaultMethod(pageKey, dataObject, fixedValue, rowData, pPageObj)
  return inputKeyValue
}
// 设置控件/表格行事件的只读或隐藏的状态--------------结束

// 三、修改固有事件的参数的方法-----------开始
export function commonUse_changeInherentEventParams (express, rowObj, modelsObj, fixedValue, pPageObj) {
  // express: 参数表达式,表达式中的变量为@变量名@console;rowObj:当前行的数据,modelsObj:当前页面的数据,fixedValue:固定参数值,调用commonUse_defaultMethod方法时需要
  let submitData = modelsObj
  if (rowObj && !Vue.prototype.$isEmptyObject(rowObj)) {
    submitData = Object.assign(JSON.parse(JSON.stringify(rowObj)), modelsObj)
  }
  let requestString = ''
  if (express) {
    // @在该字符串中的位置
    let positionTag = []
    let firstPosition = express.indexOf('@')
    while (firstPosition > -1) {
      positionTag.push(firstPosition)
      firstPosition = express.indexOf('@', firstPosition + 1)
    }
    // 需要替换的key的集合
    let modelsKeyArray = []
    for (let i = 0; i < positionTag.length; i = i + 2) {
      modelsKeyArray.push(express.slice(positionTag[i] + 1, positionTag[i + 1]))
    }
    // 替换express中对应的值
    for (let i = 0; i < modelsKeyArray.length; i++) {
      // 需要判断是不是固定的参数
      if (modelsKeyArray[i].indexOf('$_') !== -1) {
        let replaceVal = commonUse_defaultMethod(modelsKeyArray[i], null, fixedValue, null)
        express = express.replace('@' + modelsKeyArray[i] + '@', replaceVal)
      } else {
        // 判断表达式是否带有R. ===表示的是变量在行资料中的
        if (modelsKeyArray[i].indexOf('R.') !== -1) {
          let inRowKey = modelsKeyArray[i].split('.')[1]
          if (rowObj && !Vue.prototype.$isEmptyObject(rowObj)) {
            let resultValue = rowObj[inRowKey]
            // 如果值是数组类型的，需要转换为字符串
            if (resultValue && Vue.prototype.$isArray(resultValue)) {
              resultValue = JSON.stringify(resultValue)
            }
            express = express.replace('@' + modelsKeyArray[i] + '@', resultValue)
          }
        } else if (modelsKeyArray[i].indexOf('P.') !== -1) {
          let inRowKey = modelsKeyArray[i].split('.')[1]
          if (pPageObj && !Vue.prototype.$isEmptyObject(pPageObj)) {
            let resultValue = pPageObj[inRowKey]
            // 如果值是数组类型的，需要转换为字符串
            if (resultValue && Vue.prototype.$isArray(resultValue)) {
              resultValue = JSON.stringify(resultValue)
            }
            express = express.replace('@' + modelsKeyArray[i] + '@', resultValue)
          }
        } else {
          if (Object.keys(submitData).indexOf(modelsKeyArray[i]) !== -1) {
            let replaceVal = submitData[modelsKeyArray[i]] ? submitData[modelsKeyArray[i]] : ''
            // 如果值是数组类型的，需要转换为字符串
            if (replaceVal && Vue.prototype.$isArray(replaceVal)) {
              replaceVal = JSON.stringify(replaceVal)
            }
            express = express.replace('@' + modelsKeyArray[i] + '@', replaceVal)
          }
        }
      }
    }
    requestString = btoa(encodeURIComponent(express))
  }
  return requestString
}
// 修改固有事件的参数的方法-----------结束

// 四、修改事件请求结束后model的参数--------开始
export function commonUse_changeOutputParams (data, eventItemNo, outputArray, modelsObj, fixedValue) {
  // data:事件触发后得到的数据源,eventItemNo触发的事件的编号,outputArray:配置的事件响应词典表,modelsObj:当前页面的数据,fixedValue:固定参数值,调用commonUse_defaultMethod方法时需要
  let dataResultArray = []
  if (outputArray && outputArray.length && eventItemNo) {
    outputArray.forEach((item, index) => {
      if (item.eventNo === eventItemNo && item.pageKey && item.apiKey) {
        let dataValue = null
        if (data) {
          if (Vue.prototype.$isArray(data) && data.length) {
            dataValue = commonUse_changeOutputParams_getValue(item, data[0], modelsObj, fixedValue)
          } else if (!Vue.prototype.$isArray(data) && !Vue.prototype.$isEmptyObject(data)) {
            dataValue = commonUse_changeOutputParams_getValue(item, data, modelsObj, fixedValue)
          }
        } else {
          dataValue = commonUse_changeOutputParams_getValue(item, null, modelsObj, fixedValue)
        }
        dataResultArray.push({
          pageKey: item.pageKey,
          pageValue: dataValue,
          index: index
        })
      }
    })
  }
  return dataResultArray
}
// 获取响应词典表的值
const commonUse_changeOutputParams_getValue = function (item, valueObj, modelsObj, fixedValue) {
  if (item.apiKey.indexOf('$_') === 0) {
    return commonUse_defaultMethod(item.apiKey, modelsObj, fixedValue, null)
  }
  if (!valueObj) {
    return null
  }
  let apiKeyArray = item.apiKey.split('.')
  // 定义变量，保存词典表中对应返回的值
  let resultValue = null
  let dataObjValue = JSON.parse(JSON.stringify(valueObj))
  for (let i = 0; i < apiKeyArray.length; i++) {
    dataObjValue = dataObjValue[apiKeyArray[i]]
    resultValue = dataObjValue
  }
  return resultValue
}
// 修改事件请求结束后model的参数--------结束

// 五、获取关联的元素------开始
export function commonUse_getRelatedComponents (list, modelKey) {
  let relatedItem = null
  if (list.length) {
    for (let i = 0; i < list.length; i++) {
      if (list[i].type === 'grid') {
        list[i].columns.forEach(item => {
          if (item.list.length) {
            for (let n = 0; n < item.list.length; n++) {
              if (item.list[n].model === modelKey) {
                relatedItem = item.list[n]
                break
              }
            }
          }
        })
      } else if (list[i].type === 'tabs') {
        if (list[i].tabList.length) {
          list[i].tabList.forEach(item => {
            for (let n = 0; n < item.list.length; n++) {
              if (item.list[n].type === 'grid') {
                const tabGrid = item.list[n].columns
                if (tabGrid.length) {
                  for (let it = 0; it < tabGrid.length; it++) {
                    for (let nt = 0; nt < tabGrid[it].list.length; nt++) {
                      if (tabGrid[it].list[nt].model === modelKey) {
                        relatedItem = tabGrid[it].list[nt]
                        break
                      }
                    }
                  }
                }
              } else {
                if (item.list[n].model === modelKey) {
                  relatedItem = item.list[n]
                  break
                }
              }
            }
          })
        }
      } else {
        if (list[i].model === modelKey) {
          relatedItem = list[i]
          break
        }
      }
    }
  }
  return relatedItem
}
// 身份证校验
export function isIdentityId (identityId) {
  // 长度或格式校验
  var patrn = /(^\d{15}$)|(^\d{17}(\d|X|x)$)/
  // 地区校验
  var aCity = {
    11: '北京',
    12: '天津',
    13: '河北',
    14: '山西',
    15: '内蒙古',
    21: '辽宁',
    22: '吉林',
    23: '黑龙江',
    31: '上海',
    32: '江苏',
    33: '浙江',
    34: '安徽',
    35: '福建',
    36: '江西',
    37: '山东',
    41: '河南',
    42: '湖北',
    43: '湖南',
    44: '广东',
    45: '广西',
    46: '海南',
    50: '重庆',
    51: '四川',
    52: '贵州',
    53: '云南',
    54: '西藏',
    61: '陕西',
    62: '甘肃',
    63: '青海',
    64: '宁夏',
    65: '新疆',
    71: '台湾',
    81: '香港',
    82: '澳门',
    91: '国外'
  }
  // 出生日期验证
  let sBirthday = (
    identityId.substr(6, 4) +
    '-' +
    Number(identityId.substr(10, 2)) +
    '-' +
    Number(identityId.substr(12, 2))
  ).replace(/-/g, '/')
  let d = new Date(sBirthday)
  // 身份证号码校验 最后4位  包括最后一位的数字/字母X
  let sum = 0
  let weights = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2]
  let codes = '10X98765432'
  for (let i = 0; i < identityId.length - 1; i++) {
    sum += identityId[i] * weights[i]
  }
  // 计算出来的最后一位身份证号码
  let last = codes[sum % 11]
  let errorMsg = ''
  if (identityId === '') {
    errorMsg = '身份证号不能为空'
  } else if (!patrn.exec(identityId)) {
    errorMsg = '你输入的身份证长度或格式错误'
  } else if (!aCity[parseInt(identityId.substr(0, 2))]) {
    errorMsg = '你的身份证地区非法'
  } else if (sBirthday !== d.getFullYear() + '/' + (d.getMonth() + 1) + '/' + d.getDate()) { errorMsg = '身份证上的出生日期非法' } else if (identityId[identityId.length - 1] !== last) {
    errorMsg = '你输入的身份证号非法'
  }
  return errorMsg
}
/**
 * 对象深度Copy
 * @param {Object} obj
 * @returns
 */
export function deepCopy (obj) {
  return JSON.parse(JSON.stringify(obj))
}
const isDef = function (v) {
  return v !== undefined && v !== null
}
/**
 * 判断对象是否为Promise
 */
export function isPromise (val) {
  return (
    isDef(val) &&
    typeof val.then === 'function' &&
    typeof val.catch === 'function'
  )
}
/**
 * 执行JS脚本
 * @param {string} fn Js
 */
export function excuteJS (fn) {
  let Fn = Function
  let logininfo = {
    userName: store.state.userName,
    userUid: store.state.userUid,
    userType: store.state.userType,
    userNo: store.state.userNo,
    roleNo: store.state.roleNo,
    loginId: store.state.nameId
  }
  let js = 'var loginInfo=' + JSON.stringify(logininfo) + '\n'
  js += fn
  return new Fn(js)()
}
/**
 * 创建文件下载-base64
 * @param {*} file_name 文件名称
 * @param {*} file_type 文件类型
 * @param {*} file_length 文件长度
 * @param {*} file_content 文件内容
 */
export function createDownloadLink4Base64 (file_name, file_type, file_length, file_content) {
  let content = decodeURIComponent(file_content)
  let blobContent = toBlob(content, file_type)
  let filename = file_name
  if ('msSaveOrOpenBlob' in navigator) {
    // Microsoft Edge and Microsoft Internet Explorer 10-11
    window.navigator.msSaveOrOpenBlob(blobContent, filename)
  } else {
    // 创建隐藏的可下载链接
    var eleLink = document.createElement('a')
    eleLink.download = filename
    eleLink.style.display = 'none'
    // 字符内容转变成blob地址
    eleLink.href = URL.createObjectURL(blobContent)
    // 触发点击
    document.body.appendChild(eleLink)
    eleLink.click()
    // 然后移除
    document.body.removeChild(eleLink)
  }
}
/**
 * 创建文件下载-base64
 * @param {*} file_link link
 * @param {*} file_name 文件名称
 */
export function createDownloadLink4BinaryLink (file_link, file_name) {
  let newfileurl = file_link
  // 创建隐藏的可下载链接
  var eleLink = document.createElement('a')
  eleLink.download = file_name
  eleLink.style.display = 'none'
  // 字符内容转变成地址
  eleLink.href = newfileurl
  // 触发点击
  document.body.appendChild(eleLink)
  eleLink.click()
  // 然后移除
  document.body.removeChild(eleLink)
}
// 获取关联的元素------结束
export {
  commonUse_defaultMethod
}
